import numpy as np
import glob
import cv2
import os
import sys
from scipy import ndimage
import matplotlib.pyplot as plt
from datetime import datetime
import configparser

def particlecount(img,y0,x0):
   # Taken from here:
   #https://stackoverflow.com/questions/16110649/counting-particles-using-image-processing-in-python
  
   # Crop image first:
   img = img[y0:,x0:]
   
   grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   grey = cv2.GaussianBlur(grey, (5,5), 0)
   maxValue = 255
   adaptiveMethod = cv2.ADAPTIVE_THRESH_GAUSSIAN_C#cv2.ADAPTIVE_THRESH_MEAN_C #cv2.ADAPTIVE_THRESH_GAUSSIAN_C
   thresholdType = cv2.THRESH_BINARY#cv2.THRESH_BINARY #cv2.THRESH_BINARY_INV
   blockSize = 3 #odd number like 3,5,7,9,11
   C = -1 # constant to be subtracted (original: -3)
   img_thresholded = cv2.adaptiveThreshold(grey, maxValue, adaptiveMethod, thresholdType, blockSize, C) 
   labelarray, n_particles = ndimage.measurements.label(img_thresholded)
   
   return n_particles
  
   

def analyse_and_save_data(path,fname,ext,y0,x0):   
   bg = []
   bg.append(cv2.bgsegm.createBackgroundSubtractorCNT())
   bg.append(cv2.bgsegm.createBackgroundSubtractorGMG())
   bg.append(cv2.createBackgroundSubtractorKNN())
   bg.append(cv2.bgsegm.createBackgroundSubtractorMOG())
   bg.append(cv2.createBackgroundSubtractorMOG2())
   
   method = [str(bg[0])[28:31],str(bg[1])[28:31],str(bg[2])[21:25],str(bg[3])[28:31],str(bg[4])[21:25]]
   
   for i in range(4,len(bg)):
      filename = glob.glob(path+fname+"_subtracted_background_"+method[i]+ext)

      cap = cv2.VideoCapture(filename[0])
      ret, frame = cap.read()
      total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
      fps = int(cap.get(cv2.CAP_PROP_FPS))
      
      print("Total number of frames in video: ",total_frames)
      print("Video frame rate: ",fps)
      print("Video length: ",np.divide(total_frames,fps)," s")
      print(i)
       
      if ret is False:
         print("Cannot read video stream")
         sys.exit(1)
      
      fgbg = bg[i]
      
      count = 0
      n_particles = []

      while count < total_frames:
          ret, frame = cap.read()
          if ret == False:
             break
     
          fgmask = fgbg.apply(frame)

          fg = cv2.copyTo(frame,fgmask)

          k = cv2.waitKey(30) & 0xff
          if k == 27:
              break
   
          n = particlecount(fg,y0,x0)
          count = count + 1
          
          n_particles.append(n)
          
      cap.release()
      cv2.destroyAllWindows()
      
      np.savetxt(path+fname+"_particlecount_"+method[i]+".csv",n_particles,header="Total frames: "+str(total_frames)+"\nFrame rate: "+str(fps),comments="# ")
   
   
   
     
def use_config(config,videofile): 
   folder = config['Global']['path']+config[videofile]['path']
   ext = ".avi"
   y0 = np.int(config[videofile]['y0'])
   x0 = np.int(config[videofile]['x0'])
   return folder,ext,y0,x0


def main(videofile=None):      
   # Initiate configparser:
   config = configparser.ConfigParser()
   # Set the path to the directory where this script is located:
   path = os.path.join(os.path.dirname(__file__), '')
   # Load configuration file:
   config.read(path+'crop.ini')
   
   if videofile == None:
       videofile = (config['Global']['files']).split()
       for f in range(0,len(videofile)):
           (folder,ext,y0,x0) = use_config(config,videofile[f])
           analyse_and_save_data(folder,videofile[f],ext,y0,x0)
   else:
	   (folder,ext,y0,x0) = use_config(config,videofile)
	   analyse_and_save_data(folder,videofile,ext,y0,x0)
   

if __name__ == "__main__":
   start = datetime.utcnow()
   print("Start: ",start)
   
   global videofile
   videofile = None
   
   if len(sys.argv) == 2:
	   videofile = sys.argv[1]
	   main(videofile)
   else:
       main(videofile) 

   print("Stop:  ",datetime.utcnow())
